//============================================================================
// Name        : TestLib.cpp
// Author      : CRMA
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <map>
#include <utility>
#include <limits>
#include <list>

#include "uniform.h"
#include "RandN.h"
#include "NumericStatistics.h"
#include "gcd.h"


using namespace std;





void Test_GCDDivBased(long a, long b)
{

	std::map<int, GCDBase::GcdBaseClassFactory *> factories;

	factories[1] = &GCDSubBased::myFactory;
	factories[2] = &GCDDivBased::myFactory;
	factories[3] = &GCDRecursive::myFactory;
	GCDBase* gcd = NULL; // = new(GCDDivBased) ;
	gcd = someMethod(factories, 1);

	if(NULL != gcd){
		int n = gcd->gcd(a,b);

		cout << "GCD div(" << a << "," << b << ")=" << n << "\t\tIterations:" << gcd->iterations() << endl;

		delete(gcd);
	}
}

void Test_GCDSubBased(long a, long b)
{

	GCDBase* gcd = new(GCDSubBased);

	int n = gcd->gcd(a,b);

	cout << "GCD sub(" << a << "," << b << ")=" << n << "\t\tIterations:" << gcd->iterations() << endl;

	delete(gcd);
}




#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;




class GcdCalculator{

public:
	GcdCalculator(){
		_iterations = 0;
	}
	unsigned long operator() (pair<unsigned long, unsigned long> naturalPair/*, int iter*/){
		_iterations++;		// wrong we need a constuctor
		if (0 == naturalPair.second) {
			return (naturalPair.first);
		} else {
			return (this->operator ()(std::make_pair(naturalPair.second, naturalPair.first % naturalPair.second)/*, iter*/));
		}
	}
	/*
		_iterations = 0;
		_pair = naturalPair;
		if (0 == _pair.first) {
			_iterations++;
			return (_pair.second);
		}
		while (_pair.second != 0) {
			if (_pair.first > _pair.second) {
				_pair.first = _pair.first - _pair.second;
			} else {
				_pair.second = _pair.second - _pair.first;
			}
			_iterations++;
		}
		return (_pair.first);
	}
*/
	inline int iterations(  ) const { return _iterations; };

private:
	int	_iterations;
	pair<unsigned long, unsigned long>	_pair;
};



void testStatistics() {
  list<long> data(60000);

  // create random numbers
  generate(data.begin(), data.end(), rand);

  // make them go from 0 to 200
  transform(data.begin(), data.end(), data.begin(), bind2nd(modulus<long> (),
      201));

  // make them go from -100 to 100
  transform(data.begin(), data.end(), data.begin(),
      bind2nd(minus<long> (), 100));

  // gather the statistics
  NumericStatistics stats = for_each(data.begin(), data.end(), NumericStatistics());

  // print the statistics
  cout << "Mean = " << stats.mean() << "\nVariance = " << stats.variance()
      << endl;

}


int main() {
  int 	i = 0;
  long 	a;
  long 	b;
  long	r;


  pair<unsigned long, unsigned long> natural_pair;

  cout << "TestLib" << endl; //

  seed();

  for(i = 0; i < 100; i++){
    a = unif(100);
    b = unif(100 /*INT_MAX*/);
    natural_pair = std::make_pair(a, b);
    GcdCalculator gcdc;
    r = gcdc(natural_pair);
    cout << "GCDCalc(" << natural_pair.first << "," << natural_pair.second << ")=" << r << "\t\tIterations:" << gcdc.iterations() << endl;

    Test_GCDDivBased(a, b);
    Test_GCDSubBased(a, b);
  }

}





